package com.itheima.stock.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.date.DateTime;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.io.BaseEncoding;
import com.itheima.stock.constant.PermissionConstant;
import com.itheima.stock.constant.StockConstant;
import com.itheima.stock.constant.UserConstant;
import com.itheima.stock.face.StockBackendCacheFace;
import com.itheima.stock.mapper.SysPermissionMapper;
import com.itheima.stock.mapper.SysRoleMapper;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.mapper.SysUserRoleMapper;
import com.itheima.stock.pojo.domain.*;
import com.itheima.stock.pojo.entity.SysRole;
import com.itheima.stock.pojo.entity.SysUser;
import com.itheima.stock.pojo.entity.SysUserRole;
import com.itheima.stock.pojo.dto.PermissionsDTO;
import com.itheima.stock.pojo.vo.resp.PermissionsVO;
import com.itheima.stock.pojo.vo.req.*;
import com.itheima.stock.pojo.vo.resp.R;
import com.itheima.stock.pojo.vo.resp.ResponseCode;
import com.itheima.stock.process.DataProcess;
import com.itheima.stock.service.UserService;
import com.itheima.stock.utils.IdWorker;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysPermissionMapper sysPermissionMapper;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private DataProcess dataProcess;
    @Autowired
    private StockBackendCacheFace stockBackendCacheFace;

    @Override
    public SysUser findUserInfoByUserName(String userName) {
        return sysUserMapper.findUserInfoByUserName(userName);
    }

/*    @Override
    public R<UserDomain> login(LoginReqVo vo) {
        //判断参数是否合法
        if (vo == null || StringUtils.isBlank(vo.getUsername()) || StringUtils.isBlank(vo.getPassword())) {
            return R.error(ResponseCode.DATA_ERROR);
        }
        //判断验证码是否错误
        if (StringUtils.isBlank(vo.getCode()) || StringUtils.isBlank(vo.getSessionId())) {
            return R.error(ResponseCode.CHECK_CODE_ERROR);
        }
        //判断验证码是否过期
        String redisCode = (String) redisTemplate.opsForValue().get(StockConstant.CHECK_PREFIX + vo.getSessionId());
        if (StringUtils.isBlank(redisCode)) {
            return R.error(ResponseCode.CHECK_CODE_TIMEOUT);
        }
        //判断redis中缓存的验证码与输入的验证码是否匹配()忽略大小写
        if (!redisCode.equalsIgnoreCase(vo.getCode())) {
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR);
        }
        //2.根据用户名去数据库查询用户信息,获取密码的密文
        SysUser dbUser = sysUserMapper.findUserInfoByUserName(vo.getUsername());
        if (dbUser == null) {
            return R.error(ResponseCode.ACCOUNT_NOT_EXISTS);
        }
        //3.调用密码匹配器匹配输入的明文密码和数据库的密文密码
*//*        if (!passwordEncoder.matches(vo.getPassword(), dbUser.getPassword())) {
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR);
        }*//*
        //4.响应
        UserDomain userDomain = new UserDomain();
        //获取用户信息
        BeanUtils.copyProperties(dbUser, userDomain);
        //通过用户id获取角色id
        List<String> rids = sysUserRoleMapper.getRoleIdByUserId(userDomain.getId());
        //通过角色id获取目录
        List<PermissionsDTO> permissions  = sysPermissionMapper.getPermissionsDTOByRid(rids);
        List<PermissionsVO> vos = dataProcess.getMenus(permissions, PermissionConstant.TOP_PERMISSION);
//        List<PermissionsDomain> permissions = sysPermissionMapper.getPermissionsByMenusId(1236916745927790564L);
*//*        for (PermissionsDomain permission : permissions) {
            System.out.println("----------"+permission+"---------");
        }

        List<PermissionsDomain> menusDomains  = sysPermissionMapper.getMenusByRoleId(rids);

        for (MenusDomain menusDomain : menusDomains) {
            //通过目录id获取菜单
            List<PermissionsDomain> permissions = sysPermissionMapper.getPermissionsByMenusId(menusDomain.getId());
            for (PermissionsDomain permission : permissions) {
                permission.setChildren(new ArrayList<>());
            }
            menusDomain.setChildren(permissions);
        }*//*

        //将权限装载给角色
        userDomain.setMenus(vos);
        //通过角色id所有按钮
        userDomain.setPermissions(sysPermissionMapper.getPermissionsCodeByRoleId(rids));
        //将管理员信息保存到会话中
        String info=dbUser.getId()+":"+dbUser.getUsername();
        String encodeInfo = BaseEncoding.base64().encode(info.getBytes());
        userDomain.setAccessToken(encodeInfo);
        HttpSession session = request.getSession();
        session.setAttribute(UserConstant.ADMIN_ID,dbUser.getId());

        return R.ok(userDomain);
    }*/

    @Override
    public R<HashMap<String, String>> getCaptchaCode() {
        //生成验证码图片
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(250, 40, 4, 5);
        //背景为清灰
        captcha.setBackground(Color.lightGray);
        //得到验证码的码
        String checkCode = captcha.getCode();
        //使用雪花算法获得会话
        String sessionId = String.valueOf(idWorker.nextId());
        //将验证码的码和会话存入redis中并设置时间为1分钟
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        ops.set(StockConstant.CHECK_PREFIX + sessionId, checkCode, 180, TimeUnit.SECONDS);
        //获取验证码图片数据
        String imageData = captcha.getImageBase64();
        //将验证码图片数据和会话响应给前端
        HashMap<String, String> map = new HashMap<>();
        map.put("imageData", imageData);
        map.put("sessionId", sessionId);
        return R.ok(map);
    }

    @Override
    public R<PageResult<SysUserDomain>> UserPage(UserPage userPage) {

        PageHelper.startPage(userPage.getPageNum(),userPage.getPageSize());

        List<SysUserDomain> pageInfo = sysUserMapper.getSysUserDomain();
        if (CollectionUtils.isEmpty(pageInfo)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA);
        }
        PageResult<SysUserDomain> result = new PageResult<>(new PageInfo<>(pageInfo));

        return R.ok(result);
    }

    @Override
    public R saveUser(UserReqVo userReqVo) {

        //判断账号是否已存在
        if(sysUserMapper.findUserByUserName(userReqVo.getUsername())){
            return R.error(ResponseCode.ACCOUNT_EXISTS_ERROR);
        }
        //从会话中拿取管理员信息
        HttpSession session = request.getSession();
        Long adminId = (Long) session.getAttribute(UserConstant.ADMIN_ID);
        //加密明文密码
        userReqVo.setPassword(passwordEncoder.encode(userReqVo.getPassword()));

        SysUser user = new SysUser();
        //属性拷贝
        BeanUtils.copyProperties(userReqVo,user);
        user.setId(idWorker.nextId());
        user.setDeleted(UserConstant.INIT_DELETED);
        user.setCreateId(adminId);
        user.setUpdateId(adminId);
        user.setCreateTime(DateTime.now());
        user.setUpdateTime(DateTime.now());

        sysUserMapper.insert(user);
        return R.ok(ResponseCode.SUCCESS);
    }

    @Override
    public R<Map<String, Object>> getRoleInfo(String userId) {

        HashMap<String, Object> map = new HashMap<>();
        List<String> ownRoleIds = sysUserRoleMapper.getRoleIdByUserId(Long.valueOf(userId));
        List<SysRole> allRole= sysRoleMapper.getAllRoles();
        map.put("ownRoleIds",ownRoleIds);
        map.put("allRole",allRole);
        return R.ok(map);
    }
    @Override
    public R editRole(EditRole editRole) {
        sysUserRoleMapper.delRoleIdByUserId(editRole.getUserId());
        List<String> roleIds = editRole.getRoleIds();
        SysUserRole userRole = new SysUserRole();
        for (String roleId : roleIds) {
            userRole.setId(idWorker.nextId());
            userRole.setUserId(editRole.getUserId());
            userRole.setRoleId(Long.valueOf(roleId));
            userRole.setCreateTime(DateTime.now());
            sysUserRoleMapper.insert(userRole);
        }
        return R.ok(ResponseCode.SUCCESS);
    }

    @Override
    public R delUser(List<Long> userIds) {
        sysUserMapper.delUserById(userIds);
        return R.ok(ResponseCode.SUCCESS);
    }

    @Override
    public R<UserByIdDomain> getUserById(String userId) {
        UserByIdDomain users = sysUserMapper.getUserById(userId);
        return R.ok(users);
    }

    @Override
    public R editUserById(EditUserDomain editUserDomain) {
        sysUserMapper.updateUserByInfo(editUserDomain);
        return R.ok(ResponseCode.SUCCESS);
    }
}